package com.dkd.flow.rules.initiator;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.dkd.flow.emums.RuleType;
import com.dkd.flow.rules.BaseRules;
import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Rule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;
@Service
//Easy Rules 是一个简单的 Java 规则引擎，用于实现基于规则的系统
@Rule(name = "InitiatorRule", description = "以发起人为条件", priority = 1)
public class InitiatorRule {
    @Autowired
    BaseRules baseRules;
    JSONArray initiator = null;
    JSONObject initiatorData = null;
    JSONObject properties = null;
    JSONObject node = null;
    void clear() {
        node = null;
        initiator = null;
        properties = null;
    }
    @Condition
    public boolean condition(@Fact("node") JSONObject node) {
        this.clear();
        this.node = node;
        getMatchConditions();
        return initiator != null && initiator.size() > 0;
    }
    @Action
    public void action() {
        JSONObject formData = baseRules.formData;
        List<JSONObject> initiatorList = initiator.stream()
                .map(item -> (JSONObject) item)
                .collect(Collectors.toList());
        Boolean bool = initiatorList.stream()
                .anyMatch(item -> {
                    String userId = item.getString("userId");
                    // 创建 SpEL 表达式解析器
                    ExpressionParser parser = new SpelExpressionParser();
                    // 创建标准评估上下文
                    StandardEvaluationContext context = new StandardEvaluationContext();
                    // 将 formData 和 jsonItem 设置到上下文中，以便在 SpEL 表达式中使用
                    context.setVariable("formData",
                            formData);
                    context.setVariable("userId",
                            userId);
                    context.setVariable("initiatorData",
                            initiatorData);
                    // 检查 initiatorData 是否存在且包含 vModel 键
                    if (initiatorData != null && initiatorData.containsKey("vModel")) {
                        String vModel = initiatorData.getString("vModel");
                        if (formData.containsKey(vModel)) {
                            JSONArray fieldValues = formData.getJSONArray(vModel);
                            for (int i = 0; i < fieldValues.size(); i++) {
                                JSONObject fieldValue = fieldValues.getJSONObject(i);
                                if (fieldValue != null && fieldValue.containsKey("userId")) {
                                    String formUserId = fieldValue.getString("userId");
                                    if (userId.equals(formUserId)) {
                                        return true;
                                    }
                                }
                            }
                        }
                    }
                    return false;
                });
        setResult(bool);
    }
    void getMatchConditions() {
        properties = node.getJSONObject("properties");
        if (!properties.isEmpty()) {
            initiator = properties.getJSONArray(RuleType.INITIATOR_RULE.value);
            initiatorData = properties.getJSONObject("initiatorData");
        }
    }
    void setResult(Boolean bool) {
        JSONObject userAssigneeRule = new JSONObject();
        userAssigneeRule.put("result",
                bool);
        userAssigneeRule.put("nodeId",
                node.getString("nodeId"));
        userAssigneeRule.put("ruleType",
                RuleType.INITIATOR_RULE.value);
        userAssigneeRule.put("ruleTypeName",
                RuleType.INITIATOR_RULE.name);
        userAssigneeRule.put("priority",
                properties.getIntValue("priority"));
        baseRules.ruleResult.add(userAssigneeRule);
    }
}
